//
//  XMManager.swift
//  XMPurchase
//
//  Created by Wxm on 2021/2/24.
//

import Foundation
import StoreKit
import XMAPI
let IAPORDER = "IAPOrder"
let needClear = "needClear"
let retryMaxTime = 3 //每次运行最多重试几次
let cheackUndoneMaxTime = 10 //同一笔订单最多重试几次
let payMentId = "payMentId" //订单号字段，可以在这里设置
enum LKPaymentStatus:Int {
    case LKPaymetEnterPayment = 98// 调用到支付接口
    case LKPaymentPrepare = 99// 预支付状态
    case LKPaymentWillStart = 100// 即将开始支付状态
    case LKPaymentRequestProductsInfo = 101// 请求商品列表状态
    case LKPaymentCharging = 102// 正在支付状态
    case LKPaymentAppleFinish = 103// 苹果服务器通讯完成
    case LKPaymentVerify = 104// 服务器正在进行验证
    case LKPaymentComplete = 110//交易完成
}

@objc public class XMManager: NSObject {
    
    @objc public weak var XMDelegate:XMPurchaseProtocol? = nil
    
    var Products:[SKProduct] = []
    /// 当前进行的交易状态
    var paymentStatus:LKPaymentStatus = LKPaymentStatus.LKPaymetEnterPayment
    
    /// 当前正在进行交易的产品id
    var paymentIdentifier = ""
    /// 当前正在进行交易的初始化订单号
    var paymentId = ""
    
    /// 当前重试次数
    var currentRetry = 0
    /// 初始化配置文件
    var config:[String:String]? = {()-> [String:String]? in
        var dic:[String:String] = NSMutableDictionary.init() as! [String : String]
        let path = Bundle.XMBundle.path(forResource: "ok_config", ofType: "cfg") ?? ""
        print("xmbundle path = " + path)
        //        do{
        //            let contentStr = try String.init(contentsOfFile: path, encoding: .utf8)
        //        }
        //        catch{
        //
        //        }
        guard let contentStr = try? String.init(contentsOfFile: path, encoding: .utf8) else {
            XMLog("配置文件不能为空")
            //            assert(true, "配置文件不能为空")
            return nil
        }
        let array = contentStr.components(separatedBy: "\n")
        for item:String in array {
            var temp = item
            temp = temp.replacingOccurrences(of: " ", with: "")
            temp = temp.replacingOccurrences(of: "\n", with: "")
            temp = temp.replacingOccurrences(of: "\r", with: "")
            let keyValue:Array<String> = temp.components(separatedBy: "=")
            if keyValue.count == 2 {
                dic.updateValue(keyValue.last!, forKey: keyValue.first!)
            }
        }
        return dic
    }()
    
    /// 初始化
    @objc public static let shareManager:XMManager = {
        let manager = XMManager()
        SKPaymentQueue.default().add(manager)
        //标记开始进行内购
        manager.paymentStatus = LKPaymentStatus.LKPaymetEnterPayment
        #warning("针对不同版本判断是否去掉👇")
        if manager.config?["needClearLocalData"] == "1" {
            manager.deleteLocalAndApplePurcheaseData()
        }else if manager.config?["needClearLocalData"] == "0" {
            if UserDefaults.standard.value(forKey: needClear) == nil {
                manager.deleteLocalAndApplePurcheaseData()
                UserDefaults.standard.setValue("1", forKey: needClear)
            }
        }
        return manager
    }()
    
    @objc public func deleteLocalAndApplePurcheaseData(){
        let fileManager = XMFileManager.init()
        //是否需要删除本地数据
        fileManager.deleteKeychian(keyToSearchFor: IAPORDER)
        fileManager.deleteArchiver(fileName: IAPORDER)
        fileManager.removeUserDf(key: IAPORDER)
        //删除apple远程订单
        finishAppleTransaction()
    }
    // MARK: - 进入游戏即调用一下查询所有商品，然后保存到本地，方便下次直接购买
    
    /// 请求产品列表
    /// - Parameter productIds: set类型的productIds 集合
    @objc public func addProductsRequest(productIds:Set<String>){
        XMLog("---请求对应的产品信息---")
        if !SKPaymentQueue.canMakePayments() {
            XMLog("当前设备不允许进行内购服务")
            return
        }
        
        //        if let products = self.Products {
        //            //从本地拿
        //            //只是查询列表，没有进行内购
        //            self.XMDelegate?.didReceivedProducts(products: products)
        //
        //            //标记结束，防止下次支付不能进行
        //            self.paymentStatus = LKPaymentStatus.LKPaymentComplete
        //        }else{
        if self.paymentStatus != LKPaymentStatus.LKPaymentPrepare {
            //直接查询商品列表，并没有进行内购
            self.paymentStatus = LKPaymentStatus.LKPaymentRequestProductsInfo
        }
        let request =  SKProductsRequest.init(productIdentifiers:productIds)
        request.delegate = self
        request.start()
        //        }
        
    }
    
    // MARK: - 支付入口
    
    /// 开始支付请求
    /// - Parameter param: 支付参数->进行预支付请求
    @objc public func XMPreparePayment(_ param: [String:Any]){
        XMLog(self.paymentStatus)
        LKProgressHUD.show()
        if !SKPaymentQueue.canMakePayments() {
            XMLog("当前设备不允许进行内购服务")
            LKProgressHUD.dismiss()
            return
        }
        if self.paymentStatus != LKPaymentStatus.LKPaymentComplete && self.paymentStatus != LKPaymentStatus.LKPaymetEnterPayment  {
            XMLog("订单正在处理中，请稍后再试")
            LKProgressHUD.dismiss()
            return
        }
        
        self.paymentIdentifier = param["productId"] as! String
        
        //        var inOutParam = param
        self.requestPrepaireNetwork(param: param) { (result) in
            if result {
                //请求预支付接口成功
                //标记开始进行支付
                self.paymentStatus = LKPaymentStatus.LKPaymentWillStart
                
                //查询本地本地是否有产品列表
                if self.Products.count > 0 {
                    print("查询到本地本地有产品列表")
                    var searched:Bool = false
                    //有,不用再进行网络请求
                    for item in self.Products {
                        if item.productIdentifier == self.paymentIdentifier {
                            //找到对应的商品
                            let payment = SKMutablePayment.init(product: item)
                            SKPaymentQueue.default().add(payment)
                            //标记正在进行支付
                            self.paymentStatus = LKPaymentStatus.LKPaymentCharging
                            searched = true
                            break
                        }
                    }
                    if searched == false {
                        //查询一下产品列表
                        print("查询到本地本地有产品列表,单没有找到--需要从服务器拉取")
                        let request =  SKProductsRequest.init(productIdentifiers:[self.paymentIdentifier ])
                        request.delegate = self
                        request.start()
                    }
                    
                }
                else {
                    //查询一下产品列表
                    print("查询不到本地本地有产品列表--需要从服务器拉取")
                    let request =  SKProductsRequest.init(productIdentifiers:[self.paymentIdentifier ])
                    request.delegate = self
                    request.start()
                }
                
                
            }else{
                //请求预支付接口失败
                LKProgressHUD.dismiss()
                self.XMDelegate?.payFailed(reason: "请求预支付接口失败", errorCode: -10)
            }
        }
    }
    
    /// 查询未完成订单
    /// - Returns: 是否有未完成订单
    @objc public func retryUnDoneOrder()->Bool{
        XMLog("---开始查询未完成的订单---")
        LKProgressHUD.show()
        self.consumeIAPORDER(isTry: true)
        
        return false
    }
    
    // MARK: - 一些工具🔧
    
    func toPostString(params:[String:Any]) -> String {
        var str = ""
        for item in params {
            if item.value is String {
                str = str.appending(item.key).appending("=").appending((item.value as! String)).appending("&")
            }else if item.value is NSNumber {
                let tempStr:String = (item.value as! NSNumber).stringValue
                str = str.appending(item.key).appending("=").appending(tempStr).appending("&")
            }else{
                let tempStr:String = String(item.value as! Int)
                str = str.appending(item.key).appending("=").appending(tempStr).appending("&")
            }
            
        }
        str.remove(at: str.index(str.endIndex, offsetBy: -1))
        return str
    }
    
    /// 保存订单到本地（订单数组：其实就是请求验证接口的参数param的数组）
    /// - Parameter param: 订单信息
    func saveDataWithAllWays<T>(param:inout T) {
        //保存到偏好设置..
        let fileManager = XMFileManager.init()
        //判断参数如果是字典类型，就先取出数组，再添加，再保存
        if param is NSDictionary {
            let param = param as! [String:Any]
            var IAPORDERArray:Array<Dictionary<String, Any>>
            var userdf:Array<Dictionary>? = fileManager.getFromUserDf(key: IAPORDER) as? Array<Dictionary<String, Any>>
            if userdf != nil {
                userdf!.removeAll(where: {$0[payMentId] as! String == param[payMentId] as! String })
                userdf!.append(param)
                IAPORDERArray = userdf!
            }else{
                //如果为空就创建一个数组
                IAPORDERArray = [param]
            }
            _ = fileManager.saveToUserDf(value:IAPORDERArray, key: IAPORDER)
            
            //保存到本地..先取出数组，再添加，再保存
//            let dispatchQueue = DispatchQueue.global()
//            dispatchQueue.async {
                var IAPORDERArray1:Array<Dictionary<String, Any>>
                var arch:Array<Dictionary>? = fileManager.getArchiver(fileName: IAPORDER) as? Array<Dictionary<String, Any>>
                
                if arch != nil {
                    arch!.removeAll(where: {$0[payMentId] as! String == param[payMentId] as! String })
                    arch!.append(param)
                    IAPORDERArray1 = arch!
                }else {
                    IAPORDERArray1 = [param]
                }
                _ =  fileManager.saveToArchiver(obj: IAPORDERArray1, fileName: IAPORDER)
//            }
            
            //保存到钥匙串 KeyChain..先取出数组，再添加，再保存
//            dispatchQueue.async {
                var IAPORDERArray2:Array<Dictionary<String, Any>>
                var keychainArr:Array<Dictionary>? = fileManager.queryDataFromKeyChain(keyToSearchfor: IAPORDER) as? Array<Dictionary<String, Any>>
                if keychainArr != nil {
                    keychainArr!.removeAll(where: {$0[payMentId] as! String == param[payMentId] as! String })
                    keychainArr!.append(param)
                    IAPORDERArray2 = keychainArr!
                }else {
                    IAPORDERArray2 = [param]
                }
                
                fileManager.savetoKeyChain(key: IAPORDER, value: IAPORDERArray2)
//            }
        }
        else if param is Array<Any> {
            //如果是数组，就直接保存
            let array = param  as! Array<Any>
            if array.count == 0 {
                fileManager.removeUserDf(key: IAPORDER)
                fileManager.deleteArchiver(fileName: IAPORDER)
                fileManager.deleteKeychian(keyToSearchFor: IAPORDER)
            }else{
                _ = fileManager.saveToUserDf(value:array, key: IAPORDER)
                _ =  fileManager.saveToArchiver(obj: array, fileName: IAPORDER)
                fileManager.savetoKeyChain(key: IAPORDER, value: array)
            }
            
        }
        
    }
    
}
// MARK: - 网络请求

extension XMManager{
    /// 预支付请求
    /// - Parameters:
    ///   - param: 预支付参数
    ///   - andResult: 预支付订单结果
    func requestPrepaireNetwork(param: [String:Any],andResult:@escaping (Bool)->Void) {
        //        let developer = self.config?["debug"]
        
        let isOnline = Bool(self.config?["isOnLine"] ?? "false") ?? false
        
        var Url:String! = self.config?["payPermissionUrlTest"]
        if isOnline {
            Url = self.config?["payPermissionUrlOnline"]
        }
        print("预支付string = \(self.toPostString(params: param))")
        let postBody = self.toPostString(params: param).data(using: .utf8)
        
        let request = NSMutableURLRequest.init(url: NSURL.init(string:Url)! as URL)
        request.timeoutInterval = 30
        request.cachePolicy = .reloadIgnoringLocalCacheData
        request.httpMethod = "POST"
        request.httpBody = postBody
        var paramk = param
        let task:URLSessionDataTask = URLSession.shared.dataTask(with: request as URLRequest) { (data: Data?, response: URLResponse?, error: Error?) in
            if error != nil {
                XMLog(error!)
                andResult(false)
            }else
            {
                if let httpResponse = response as? HTTPURLResponse {
                    
                    if httpResponse.statusCode == 200 {
                        if (data != nil) {
                            do {
                                guard let dic = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? Dictionary<String, Any> else {
                                    return
                                }
                                guard let result =  dic["result"] as? NSNumber else {
                                    return
                                }
                                if result.intValue == 1{
                                    self.paymentId = dic[payMentId] as! String
                                    //将订单号加入到列表
                                    paramk.updateValue(self.paymentId, forKey: payMentId)
                                    //保存订单信息
                                    self.saveDataWithAllWays(param: &paramk)
                                    XMLog("进行 保存订单信息到本地的操作")
                                    andResult(true)
                                }else{
                                    XMLog("初始化预支付失败\(result)")
                                }
                                
                            } catch  {
                                XMLog("请求 转化json失败")
                            }
                            
                        }else{andResult(false)}
                        
                    }else{
                        andResult(false)
                    }
                }
            }
            
        }
        
        task.resume()
        //标记执行完毕预支付
        self.paymentStatus = LKPaymentStatus.LKPaymentPrepare
        
    }
    
    /// 订单校验
    /// - Parameter param: 参数
    /// - Returns: 是否成功
    func sendRequestToServerWithiAPOrder(params:inout [String:Any],andResult:@escaping (Bool,Int)->Void) {
        //        let developer = self.config?["debug"]
        let isOnline = Bundle.main.infoDictionary!["isOnLine"] as! Bool
        var Url:String! = self.config?["notifyUrlTest"]
        if isOnline {
            Url = self.config?["notifyUrlOnline"]
        }
        //如果没有保存transactionReceipt，就从本地取，否则就是老订单，不用再重新取
        let trans = params["transactionReceipt"] as? String
        
        if  trans == nil || trans?.count == 0 {

            if  let receiptURL = Bundle.main.appStoreReceiptURL {
                do {
                    let receiptData = try Data.init(contentsOf: receiptURL)
                    let reciptStr:String = receiptData.base64EncodedString(options: NSData.Base64EncodingOptions.init(rawValue: 0))
                    params.updateValue(reciptStr, forKey: "transactionReceipt")

                } catch  {
                    XMLog("receiptData 转化失败")
                }

            }else {
                XMLog("receiptURL -nil- error")
            }

            #warning("在这里提前调用andResult，回调里面会报错，必须新建个线程DispatchQueue.global().async {andResult(false,0)}")
        }
    
        let postBody = self.toPostString(params: params).data(using: .utf8)
        let request = NSMutableURLRequest.init(url: NSURL.init(string:Url)! as URL)
        request.timeoutInterval = 15
        request.cachePolicy = .reloadIgnoringLocalCacheData
        request.httpMethod = "POST"
        request.httpBody = postBody
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.setValue(String(describing: postBody?.count), forHTTPHeaderField: "Content-Length")
        let task:URLSessionDataTask = URLSession.shared.dataTask(with: request as URLRequest) { (data: Data?, response: URLResponse?, error: Error?) in
            if error != nil {
                XMLog(error!)
                self.currentRetry += 1
                andResult(false,0)
            }
            else
            {
                if let httpResponse = response as? HTTPURLResponse {
                    XMLog("Status code: (\(httpResponse.statusCode))")
                    if httpResponse.statusCode == 200 {
                        //校验成功
                        //移除本地保存的订单数据
                        let result = String.init(data: data!, encoding: .utf8)
                        if result == "1" || result == "-1472" {
                            self.currentRetry = 0
                            XMLog("💖支付回调成功-\(String(describing: result))")
                            andResult(true,1)
                        }else{
                            self.currentRetry += 1
                            XMLog("❎支付回调失败-\(String(describing: result))")
                            andResult(false,Int(result ?? "0") ?? 0)
                        }
                        
                    }else{
                        self.currentRetry += 1
                        andResult(false,httpResponse.statusCode)
                    }
                    
                }
            }
            
        }
        
        task.resume()
        
    }
}
// MARK: - skpayment delegate

extension XMManager: SKProductsRequestDelegate,SKPaymentTransactionObserver{
    
    public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        
        if self.paymentStatus == LKPaymentStatus.LKPaymentRequestProductsInfo  {
            //查询结构保存到本地
            if response.products.count > 0 {

                self.Products.append(contentsOf: response.products)
            }
            //只是查询列表，没有进行内购
            self.XMDelegate?.didReceivedProducts(products: response.products)
            
            //标记结束，防止下次支付不能进行
            self.paymentStatus = LKPaymentStatus.LKPaymentComplete
        }
        //调用完毕预支付后回调内已经修改成LKPaymentWillStart，可以进行购买
        if self.paymentStatus == LKPaymentStatus.LKPaymentWillStart {
            //保存一下查询结果。下次调取支付更快
            if response.products.count > 0 {
                self.Products.append(contentsOf: response.products)
            }
            //开始调用支付
            var find:Bool = false
            for item in response.products {
                if item.productIdentifier == self.paymentIdentifier {
                    //找到对应的商品
                    let payment = SKMutablePayment.init(product: item)
                    SKPaymentQueue.default().add(payment)
                    find = true
                    //标记正在进行支付
                    self.paymentStatus = LKPaymentStatus.LKPaymentCharging
                }
            }
            if !find {
                XMLog("没有找到对应商品")
            }
            
        }
    }
    
    public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        //标记支付完成 苹果服务器通讯完成
        //如果程序中途突然退出，再次进入后如果有未完成订单，依然会走此次回调
        self.paymentStatus = LKPaymentStatus.LKPaymentAppleFinish
        for transaction in transactions {
            if transaction.transactionState == .purchased {
                XMLog("付款成功了")
                //已经购买过了，需要验证
                //首先给一个成功回调
                //                self.XMDelegate?.paySuccess()
                // FIXME: - 先在苹果那边消耗掉这个订单，然后保存到本地。只要本地没有被消除，还是可以进行补单的.但是也有漏洞，假如用户更换手机，那么补单就不能被检测到了。要想保持换手机也能补单，只能存到applicationUsername，但是也有可能是空的。所以最保险的就是存到服务器上。
                //至于为何在此处进行消耗，因为苹果的payment.applicationUsername很有可能是空的，所以不能保存订单信息到这里，只能保存到本地，保存到本地transaction的话，userdf不能保存对象，何况对象数据量也较多，所以按本地订单来消耗最保险
                //这里可以进行更新 transactionReceipt
//                SKPaymentQueue.default().finishTransaction(transaction)
                //然后去验证
                self.consumeIAPORDER(isTry: false)
            }
            else if transaction.transactionState == .restored {
                SKPaymentQueue.default().finishTransaction(transaction)
                self.cancelIAPORDER(key: self.paymentId)
            }
            else if transaction.transactionState == .deferred {
                
                let traError = transaction.error as! SKError
                //先回调给上面
                self.XMDelegate?.payFailed(reason: "deferred",errorCode: traError.code.rawValue)
                //再删除本地保存的订单
                self.cancelIAPORDER(key: self.paymentId)
            }
            else if transaction.transactionState == .failed {
                
                var reason = ""
                let traError = transaction.error as? SKError ?? nil
                switch traError?.code {
                
                case .unknown:
                    //支付失败无法连接iTunes Store
                    reason = "支付失败无法连接iTunes Store"
                    break
                case .clientInvalid:
                    reason = "clientInvalid"
                    break
                case .cloudServiceNetworkConnectionFailed:
                    //网络连接错误
                    reason = "网络连接错误"
                    break
                case .paymentCancelled:
                    //交易取消
                    reason = "交易取消"
                    break
                case .paymentInvalid:
                    //交易无效
                    reason = "交易无效"
                    break
                case .unauthorizedRequestData:
                    //未经授权的请求数据
                    reason = "未经授权的请求数据"
                    break
                case .paymentNotAllowed:
                    //内购权限关闭
                    reason = "内购权限关闭"
                    break
                case .storeProductNotAvailable:
                    //商店产品不可用 下架某些产品
                    reason = "商店产品不可用 下架某些产品"
                    break
                default:
                    reason = "default - 支付失败无法连接iTunes Store"
                    break
                }
                SKPaymentQueue.default().finishTransaction(transaction)
                //先回调给上面
                self.XMDelegate?.payFailed(reason: reason,errorCode: traError?.code.rawValue ?? 0)
                //再删除本地保存的订单
                self.cancelIAPORDER(key: self.paymentId)
            }
        }
    }
    @objc func clearRetryTimes(){
        self.currentRetry = 0
    }
    /// 验证并消耗本地订单
    func consumeIAPORDER(isTry:Bool) {
        
        // MARK: -  取出本地订单
        var allOderFilterArray = self.getIaporderFromLocal()
        
        if isTry {
            //是重试操作
            if currentRetry == retryMaxTime {
                XMLog("👐超过重试次数👐")
                currentRetry += 1
                self.perform(#selector(clearRetryTimes), with: nil, afterDelay: 60 * 5)
                return
            }else if currentRetry > retryMaxTime {
                LKProgressHUD.dismiss()
                return
            }
            XMLog("😵😵是重试操作，检测到[\(allOderFilterArray.count)]个未完成订单")
        }
        if allOderFilterArray.count == 0 {
            //如果是订单是空的话也要标记支付完成
            XMLog("🙁🙁检测到[\(allOderFilterArray.count)]个订单")
            LKProgressHUD.dismiss()
            self.paymentStatus = LKPaymentStatus.LKPaymentComplete
            return
        }
        //用信号量来保证循环完毕所有的列表 新建最多1个线程(1个线程防止资源争抢allOderFilterArray)
        let group = DispatchGroup.init()
        let queue = DispatchQueue.init(label: "com.xmmanger",attributes: .concurrent)
        let semaphore = DispatchSemaphore.init(value: 1)
        
        for item:[String:Any] in allOderFilterArray {
            group.enter()
            var param:[String:Any] = item
            
            queue.async {
                let result = semaphore.wait(timeout: .distantFuture)
                if result == .success {
                    //网络请求，消耗订单，这里是异步的请求，所以要用到信号量，否则还是会异步执行
                    self.sendRequestToServerWithiAPOrder(params: &param) { (result,code) in
                        
                        if result {
                            XMLog("订单验证成功,payMentId=\(param[payMentId] as! String)")
                            self.finishAppleTransaction(param["transactionIdentifier"] as? String)
                            allOderFilterArray = allOderFilterArray.filter { (Item:[String:Any]) -> Bool in
                                //找到相同的payMentId的订单，然后删除
                                if param[payMentId] as! String == Item[payMentId] as! String {
                                    //回调成功
                                    self.XMDelegate?.paySuccess(order: Item)
                                    return false
                                }
                                return true
                            }
                        }
                        else {
                
                            //获取当前的transactionReceipt保存一下，如果这次校验失败了,下次再校验
                            var temparam = param
                            let retryTimes = temparam["retryTimes"] as? String ?? "0"
                            var retryTimesInt = Int(retryTimes)
                            retryTimesInt! += 1
                            temparam.updateValue(String(retryTimesInt!), forKey: "retryTimes")
                    
                            allOderFilterArray.removeAll(where: {$0[payMentId]! == temparam[payMentId] as? String })
                            allOderFilterArray.append(temparam as! Dictionary<String, String>)
                            self.XMDelegate?.payFailed(reason: "校验失败", errorCode: code)
                            XMLog("订单消耗失败,当前订单重试次数-\(temparam["retryTimes"] as? String ?? "0")")
                        }
                        //⚠️⚠️⚠️⚠️⚠️⚠️一定要先处理完毕结果再进行下一次⚠️⚠️⚠️⚠️⚠️
                        semaphore.signal()
                        group.leave()
                    }
                }
                
            }
        }
        //是否阻塞当前线程(wait ⚠️就会阻塞)
        //group.wait()
        group.notify(queue: queue) {
            //验证完毕，不管验证结果，交易完成
            self.paymentStatus = LKPaymentStatus.LKPaymentComplete
            //继续进行保存操作
          
            //删除掉所有没有付过款的重试订单(重试5次)(很重要，防止【用户初始化订单就退出app的情况】下后台一直重复失败的操作)
            XMLog("🙀🙀仍然有【\(allOderFilterArray.count)】个未完成订单：校验未支付订单前")
            allOderFilterArray = allOderFilterArray.filter{ (Item:[String:Any]) -> Bool in
                
                //找到重试过多的订单，然后删除
                if Int(Item["retryTimes"] as! String) ?? 0 >= cheackUndoneMaxTime  {
                    self.finishAppleTransaction(Item["transactionIdentifier"] as? String)
                    return false
                }
                return true
            }
//            allOderFilterArray.removeAll(where: {Int($0["retryTimes"] ?? "0") ?? 0 >= cheackUndoneMaxTime })
            XMLog("🙀🙀仍然有【\(allOderFilterArray.count)】个未完成订单：校验未支付订单后")
            if allOderFilterArray.count == 0 {
                //如果没有检查到本地未完成订单，那么就查一下apple服务器,防止不能进行购买
                self.finishAppleTransaction("")
            }
            self.saveDataWithAllWays(param: &allOderFilterArray)
            //验证完毕，不管验证结果，交易完成
            self.paymentStatus = LKPaymentStatus.LKPaymentComplete
        
        }
    }
    
    /// 删除取消支付和支付失败的订单
    /// - Parameter key: 订单key paymentId
    func cancelIAPORDER(key:String) {
        //取消后，修改状态
        self.paymentStatus = LKPaymentStatus.LKPaymentComplete
        
        // MARK: -  取出本地订单
        var allOderFilterArray = self.getIaporderFromLocal()
        print(allOderFilterArray.count)
        allOderFilterArray = allOderFilterArray.filter { (Item:[String:Any]) -> Bool in
            //找到相同的payMentId的订单，然后删除
            if key == Item[payMentId] as! String {
                return false
            }
            return true
        }
        //保存到本地
        //        if allOderFilterArray.count > 0 {
        XMLog("cancelIAPORDER-有【\(allOderFilterArray.count)】个未完成订单")
        self.saveDataWithAllWays(param: &allOderFilterArray)
        //        }
    }
    
    ///  取出本地存储的所有订单，包含userdf，Archiver 和 keychain里
    /// - Returns: 订单数组
    func getIaporderFromLocal() -> [Dictionary<String, String>] {
        //从本地拿出订单信息。然后去验证
        let fileManager = XMFileManager.init()
        
        //1.先从 userdf 取,至少有一个元素,再从Archiver取，再从keychain取。
        //取出后3个数组合并，因为有可能用户会清除沙盒数据或其他原因导致三个订单数组不一致,有可能全是空的
        let userdf = fileManager.getFromUserDf(key: IAPORDER) as? Array<Dictionary<String, Any>> ?? []
        let arch = fileManager.getArchiver(fileName: IAPORDER) as? Array<Dictionary<String, Any>> ?? []
        let keychainArr = fileManager.queryDataFromKeyChain(keyToSearchfor: IAPORDER) as? Array<Dictionary<String, Any>> ?? []
        //        print(userdf.count)
        //        print(arch.count)
        //        print(keychainArr.count)
        guard let allOderArray:Array = (userdf + arch  + keychainArr ) as? Array<Dictionary<String,String>>  else {
            XMLog("⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️合并订单失败⚠️⚠️⚠️⚠️⚠️⚠️⚠️")
            return keychainArr as? Array<Dictionary<String,String>> ?? []
        }
        // MARK: -  这里先把三个地方的订单合并，然后要去重 filterDuplicates
        let allOderFilterArray = allOderArray.filterDuplicates({$0})
        
        return allOderFilterArray
    }
    /// 关闭apple订单
    /// - Parameter transactionIdentifier: apple订单号
    private func finishAppleTransaction(_ transactionIdentifier:String? = ""){
        print("要查询的apple订单：\(String(describing: transactionIdentifier))")
        print(SKPaymentQueue.default().transactions.count)
        for transaction in SKPaymentQueue.default().transactions {
            if transactionIdentifier == transaction.transactionIdentifier ?? "" || transaction.transactionState == .purchased {
                print("apple关闭订单 transactionIdentifier == \(String(describing: transaction.transactionIdentifier)) ")
                SKPaymentQueue.default().finishTransaction(transaction)
            }
        }
    }
    @objc public func testmd5(str:String){
        XMLog(str.md5)
        LKProgressHUD.show()
    }
}
